////////////////////////////////////////////////////////////////////////////////
//
//	Original file Name: Playlist.java
//	Originating Author: JWhitefield
//	
//	Description: Represents a list of playable sounds  
//
////////////////////////////////////////////////////////////////////////////////

package com.jjw.game.sound;

import java.util.Map;

import javazoom.jlgui.basicplayer.BasicController;
import javazoom.jlgui.basicplayer.BasicPlayerEvent;
import javazoom.jlgui.basicplayer.BasicPlayerListener;

/**
 * Represents a list of playable sounds 
 * 
 * @author JWhitefield
 *
 */
public class Playlist implements BasicPlayerListener {

	//--------------------------------------------------------------------------
	//
	//Properties
	//
	//--------------------------------------------------------------------------
		
	//----------------------------------
	// Public
	//----------------------------------
	
	//----------------------------------
	//  Getters / Setters
	//----------------------------------
	
	/**
	 * Shows if the play list is playing or not
	 */
	public boolean isPlaying() {
		
		//Return play list is playing
		return this.playlistIsPlaying;
	}
	
	//----------------------------------
	// Private
	//----------------------------------
	
	/**
	 * The list of the songs will be played
	 */
	private Sound[] playlistSounds = null;
	
	/**
	 * The index of the current song that is playing
	 */
	private int currentSoundIndex = -1;
	
	/**
	 * Is the play list being looped
	 */
	private boolean loopPlaylist = false;
	
	/**
	 * Flag to show if the play list is playing
	 */
	private boolean playlistIsPlaying = false;
	
	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------
	
	//----------------------------------
	// Public
	//----------------------------------	
		
	Playlist( Sound[] playlistSounds, boolean loopPlaylist ) {
		
		//Set the play list sounds
		this.playlistSounds = playlistSounds;
		
		//Are we looping the play list
		this.loopPlaylist = loopPlaylist;
	}
		
	/**
	 * Starts the play list
	 */
	public void startPlaylist() {
		
		//If the current sound index is at -1 then start it 
		if( this.currentSoundIndex == -1 ) {
			
			//Start the play list by calling the next sound
			this.nextSound();			
		}else{
			
			//If the play list is in progress make sure the sound is playing 
			
			//Get the current sound
			Sound currentSound = this.getCurrentSound();
				
			//If the current sound is null we cant play it
			if( currentSound == null )
				return;
			
			//If the play list isn't currently playing then we will need to add the listener again 
			if( !this.playlistIsPlaying )
			{
				//Watch the current sound for any events,
				currentSound.attachObjectAsListener( this );				
			}
			
			//Check the sounds states, so that it will start playing 
			if( currentSound.isPaused() )
				currentSound.resume();
			else
				currentSound.play();
		}
		
		//Set the is playing flag
		this.playlistIsPlaying = true;
	}
	
	/**
	 * Stop the play list 
	 */
	public void stopPlaylist() {
		
		//Check the current play list index 
		if( this.currentSoundIndex == -1 )
			return;
		
		//If the current sound is null we can't stop it 
		if( this.getCurrentSound() == null )
			return;
		
		//Remove the listener from the sound 
		this.getCurrentSound().removeObjectAsListener( this );
		
		//The play list has been stopped 
		this.getCurrentSound().stop();
		
		//Set the is playing flag
		this.playlistIsPlaying = false;
	}
	
	/**
	 * Stops the play list and resets it back to the beginning
	 */
	public void resetPlaylist() {
		
		//Top the play list 
		this.stopPlaylist();
	}
	
	//----------------------------------
	// Private
	//----------------------------------

	/**
	 * Play the next sound
	 */
	private void nextSound() {
		
		//If we don't have a list of sounds then stop here
		if( this.playlistSounds == null)
			return;	
			
		//Up the index of the current sound
		this.currentSoundIndex++;
		
		//If the current sound index has reached the end of the list then bail out 
		if( this.currentSoundIndex >= this.playlistSounds.length ) {
			
			//Are we looping this play list back to the beginning, and do we have at least one sound? 
			if( this.loopPlaylist && this.playlistSounds.length > 0 ){
				
				//Yes then reset the index to zero
				this.currentSoundIndex = 0;
			}else{
			
				//As we are stopping the play list is no longer playing
				this.playlistIsPlaying = false;
				
				//No then stop here
				return; 
			}
		}
		
		//Get the next sound to play
		Sound nextSoundToPlay = this.getCurrentSound();
		
		//Is the next song to be played is null  
		if( nextSoundToPlay == null )
		{
			//If so call the next song to be played and return
			this.nextSound();
			return;
		}
		
		//Attach the play list as an listener so we know what goes on 
		nextSoundToPlay.attachObjectAsListener( this );
		
		//If we have our song play it
		nextSoundToPlay.play();
	}
	
	/**
	 * Get the current sound
	 */
	private Sound getCurrentSound() {
		
		//Check that the index has been set
		if( this.currentSoundIndex == -1  )
			return null;
		
		//Check we have play list sounds
		if( this.playlistSounds == null )
			return null;
		
		//If the current index is greater than or equal to the length return null
		if( this.currentSoundIndex >= this.playlistSounds.length ) 
			return null;
		
		//Return the sound at this index
		return this.playlistSounds[ this.currentSoundIndex ];
	}
	
	//----------------------------------
	// Overridden / Implemented
	//----------------------------------

	@SuppressWarnings("rawtypes")
	@Override
	public void opened(Object arg0, Map arg1) {}

	@SuppressWarnings("rawtypes")
	@Override
	public void progress(int arg0, long arg1, byte[] arg2, Map arg3) {}

	@Override
	public void setController(BasicController arg0) {}

	@Override
	public void stateUpdated(BasicPlayerEvent event) {

		//If the event an end of media event
		if( event.getCode() == BasicPlayerEvent.EOM ) {
			
			//Stop listening to the current sound as we have got where we need
			if( this.getCurrentSound() != null )
			{
				this.getCurrentSound().removeObjectAsListener( this );
				this.getCurrentSound().stop();
			}
			
			//Calls the next sound to be played
			this.nextSound();
		}		
	}
}
